#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <getopt.h>
#include <limits.h>
#include <inttypes.h>
#include <signal.h>

#include "database.h"
#include "scanner.h"
#include "threadpool.h"

#define DATABASE_NAME "file_hashes.db"
#define DEFAULT_MIN_SIZE (100 * 1024)  // 100KB in bytes
#define DEFAULT_THREAD_COUNT 0         // 0 means auto-detect CPU cores

// 全局变量，用于信号处理
volatile sig_atomic_t g_shutdown_requested = 0;
static sqlite3 *g_db = NULL;

/**
 * 信号处理函数
 * 处理 SIGINT (Ctrl+C) 和 SIGTERM 信号
 */
static void signal_handler(int signum) {
    if (signum == SIGINT || signum == SIGTERM) {
        g_shutdown_requested = 1;
        fprintf(stderr, "\n\n收到中断信号 (%s)，正在停止所有操作并清理资源...\n", 
                signum == SIGINT ? "SIGINT" : "SIGTERM");
    }
}

/**
 * 设置信号处理器
 */
static void setup_signal_handlers(void) {
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = signal_handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    
    if (sigaction(SIGINT, &sa, NULL) == -1) {
        fprintf(stderr, "警告: 无法设置 SIGINT 信号处理器\n");
    }
    
    if (sigaction(SIGTERM, &sa, NULL) == -1) {
        fprintf(stderr, "警告: 无法设置 SIGTERM 信号处理器\n");
    }
}

/**
 * 打印程序使用说明
 * @param program_name 程序名称
 */
static void print_usage(const char *program_name) {
    printf("用法: %s [选项] [文件路径]\n", program_name);
    printf("选项:\n");
    printf("  -s <大小>        最小文件大小 (默认: 100k)\n");
    printf("                   可使用 k/m/g 后缀 (例如: 1M, 2G)\n");
    printf("  -t <线程数>     使用的线程数 (默认: CPU核心数)\n");
    printf("  -f               强制重新计算已存在的文件\n");
    printf("  -c               清理数据库 (删除不存在的文件记录)\n");
    printf("  -l               查找重复文件 (按fileHash查找)\n");
    printf("  -h               显示此帮助信息\n");
    printf("\n");
    printf("示例:\n");
    printf("  %s /path/to/directory     # 扫描指定目录\n", program_name);
    printf("  %s -s 1M -t 8 /path       # 最小1MB，8个线程\n", program_name);
    printf("  %s -f -c /path            # 强制重算并清理数据库\n", program_name);
    printf("  %s -l                      # 查找重复文件\n", program_name);
}

/**
 * 主函数
 * 解析命令行参数并执行相应操作
 */
int main(int argc, char *argv[]) {
    const char *directory = ".";
    int64_t min_size = DEFAULT_MIN_SIZE;
    int thread_count = DEFAULT_THREAD_COUNT;
    int force_rehash = 0;
    int cleanup_db = 0;
    int list_duplicates = 0;
    
    // 设置信号处理器
    setup_signal_handlers();

    int opt;
    while ((opt = getopt(argc, argv, "s:t:fclh")) != -1) {
        switch (opt) {
            case 's': {
                int64_t size = parse_size(optarg);
                if (size < 0) {
                    fprintf(stderr, "无效的大小格式: %s\n", optarg);
                    return EXIT_FAILURE;
                }
                min_size = size;
                break;
            }
            case 't':
                thread_count = atoi(optarg);
                if (thread_count <= 0) {
                    fprintf(stderr, "无效的线程数: %s\n", optarg);
                    return EXIT_FAILURE;
                }
                break;
            case 'f':
                force_rehash = 1;
                break;
            case 'c':
                cleanup_db = 1;
                break;
            case 'l':
                list_duplicates = 1;
                break;
            case 'h':
                print_usage(argv[0]);
                return EXIT_SUCCESS;
            default:
                print_usage(argv[0]);
                return EXIT_FAILURE;
        }
    }

    // 获取文件路径参数（如果存在）
    if (optind < argc) {
        directory = argv[optind];
    }

    // 验证目录路径
    char absolute_path[MAX_PATH_LEN];
    if (realpath(directory, absolute_path) == NULL) {
        fprintf(stderr, "无法解析目录路径: %s\n", directory);
        return EXIT_FAILURE;
    }

    // 检查路径是否为目录
    struct stat st;
    if (stat(absolute_path, &st) != 0) {
        fprintf(stderr, "无法访问路径: %s\n", absolute_path);
        return EXIT_FAILURE;
    }

    if (!S_ISDIR(st.st_mode)) {
        fprintf(stderr, "路径不是目录: %s\n", absolute_path);
        return EXIT_FAILURE;
    }

    // 设置默认线程数
    if (thread_count == DEFAULT_THREAD_COUNT) {
        thread_count = sysconf(_SC_NPROCESSORS_ONLN);
        if (thread_count <= 0) {
            thread_count = 4;
        }
    }

    // 初始化数据库
    sqlite3 *db;
    if (db_initialize(DATABASE_NAME, &db) != SQLITE_OK) {
        return EXIT_FAILURE;
    }
    
    // 保存到全局变量，用于信号处理
    g_db = db;

    // 如果只是查找重复文件，直接执行并退出
    if (list_duplicates) {
        if (db_find_duplicate_files(db) != SQLITE_OK) {
            sqlite3_close(db);
            return EXIT_FAILURE;
        }
        sqlite3_close(db);
        return EXIT_SUCCESS;
    }

    // 如果只是清理数据库，直接执行并退出
    if (cleanup_db) {
        if (db_delete_nonexistent_files(db) != SQLITE_OK) {
            sqlite3_close(db);
            return EXIT_FAILURE;
        }
        sqlite3_close(db);
        return EXIT_SUCCESS;
    }

    // 扫描目录并处理文件
    int result = scan_directory(absolute_path, min_size, thread_count, force_rehash, db);

    // 确保所有线程都退出后再关闭数据库
    if (g_shutdown_requested) {
        // 给线程池销毁函数足够的时间来清理所有线程
        sleep(1);
    }

    // 关闭数据库
    sqlite3_close(db);
    g_db = NULL;

    if (g_shutdown_requested) {
        return EXIT_FAILURE;
    }

    return (result == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
